#include<bits/stdc++.h>
#define rep(i,l,r) for(ll i=(l);i<=(r);i++)
#define Rep(i,r,l) for(ll i=(r);i>=(l);i--)
using namespace std;
typedef long long ll;
ll pai[27*4],shoupai[3][14],my,win;
vector<ll>paihe[3];
vector<string>fulu[3];
ll t,len[3];
ll cntbei[3];
int top,bottom,lingshang;
ll cnt[27];
bool special[30],yaojiu[30];
ofstream fout;
void init() {
	yaojiu[0]=yaojiu[1]=yaojiu[2]=yaojiu[10]=yaojiu[11]=yaojiu[19]=1;
	special[0]=special[1]=special[9]=special[10]=special[18]=special[19]=1;
	rep(i,20,26)special[i]=yaojiu[i]=1;
}
bool chk() {
	ll tmp[27];
	rep(i,0,26)tmp[i]=cnt[i]%3;
	rep(i,0,26)if(tmp[i]) {
		if(tmp[i]<0)return 0;
		if(special[i])return 0;
		tmp[i+1]-=tmp[i],tmp[i+2]-=tmp[i];
		tmp[i]=0;
	}
	return 1;
}
bool ron() {
	ll tot=0,num=0;
	rep(i,0,26)if(cnt[i]>=2)tot++;
	if(tot==7)return 1;
	bool kokusimusou=1;
	rep(i,0,26) {
		if(cnt[i]&&!yaojiu[i])kokusimusou=0,num++;
		if(cnt[i]&&yaojiu[i])num++;
	}
	if(kokusimusou&&num==13)return 1;
	rep(i,0,26)if(cnt[i]>=2) {
		cnt[i]-=2;
		if(chk())return 1;
		cnt[i]+=2;
	}
	return 0;
}
string topai(ll x) {
	if(x==0)return "1m";
	else if(x==1)return "9m";
	x-=2;
	if(x>=0&&x<9)return char(x+'1')+string("p");
	x-=9;
	if(x>=0&&x<9)return char(x+'1')+string("s");
	x-=9;
	return char(x+'1')+string("z");
}
ll tonum(string x) {
	if(x.size()>2)return -1;
	if(x[1]=='m') {
		if(x[0]=='1')return 0;
		else if(x[0]=='9')return 1;
		else return -1;
	}
	if(x[1]=='p') {
		if(isdigit(x[0])&&x[0]!='0')return x[0]-'0'+1;
		return -1;
	}
	if(x[1]=='s') {
		if(isdigit(x[0])&&x[0]!='0')return x[0]-'0'+10;
		return -1;
	}
	if(x[1]=='z') {
		if(!isdigit(x[0]))return -1;
		ll qwq=x[0]-'0';
		if(qwq>=1&&qwq<=7)return qwq+19;
	}
	return -1;
}
void sort(ll x,bool flag=0) {
	sort(shoupai[x],shoupai[x]+len[x]+1+flag);
}
string pl(ll t) {
	if(t==0)return "东家";
	else if(t==1)return "南家";
	else return "西家";
}
void tsumo() {
	cout<<pl(my)<<"自摸"<<endl;
	fout<<pl(my)<<"自摸"<<endl;
	rep(i,0,len[my]+1)cout<<topai(shoupai[my][i])<<" ";
	cout<<"\t";
	for(string x:fulu[my])cout<<x<<" ";
	cout<<endl;
	rep(i,0,len[my]+1)fout<<topai(shoupai[my][i])<<" ";
	fout<<"\t";
	for(string x:fulu[my])fout<<x<<" ";
	fout<<endl;
	exit(0);
}
void printshoupai(bool flag=0) {
	puts("您的手牌：");
	rep(i,0,len[my]+flag)cout<<topai(shoupai[my][i])<<" ";
	cout<<"\t";
	for(string x:fulu[my])cout<<x<<" ";
	cout<<endl;
}
void dapai(bool flag=1) {
	if(flag)cnt[shoupai[my][len[my]+1]]++;
	printshoupai(1);
	if(ron()) {
		puts("是否自摸？");
		int x;
		cin>>x;
		if(x) {
			tsumo();
		}
	}
	set<ll>qwq;
	rep(i,0,26)if(cnt[i]>=4)qwq.insert(i);
	while(qwq.size()) {
		puts("是否暗杠？");
		int x;
		cin>>x;
		if(x==0)break;
		ll qie=-1;
		if(qwq.size()>1) {
			puts("请选择您暗杠的手牌，或选择不暗杠：");
			for(auto x:qwq)cout<<"--"<<topai(x)<<topai(x)<<"--"<<" ";
			cout<<endl;
			bool flag=0;
			while(qie==-1) {
				string s;
				cin>>s;
				if(s=="0") {
					flag=1;
					break;
				}
				if(!qwq.count(tonum(s))) {
					cout<<"此牌不合法或者不在您的手牌中，请重新输入！"<<endl;
					continue;
				}
				qie=tonum(s);
			}
			if(flag)break;
		} else qie=*qwq.begin();
		qwq.erase(qie);
		ll qaq=len[my]+1;
		string s=topai(qie);
		rep(i,0,len[my]-3)if(shoupai[my][i]==qie) {
			swap(shoupai[my][i],shoupai[my][qaq--]);
			if(qaq==len[my]-3)break;
		}
		cnt[qie]-=4;
		len[my]-=3;
		shoupai[my][len[my]+1]=pai[lingshang--];
		cnt[shoupai[my][len[my]+1]]++;
		if(cnt[shoupai[my][len[my]+1]]==4)qwq.insert(shoupai[my][len[my]+1]);
		fulu[my].push_back("--"+s+s+"--");
		sort(my);
		cout<<pl(my)<<"暗杠 "<<s<<endl;
		printshoupai(1);
		if(ron()) {
			tsumo();
		}
	}
	while(flag&&cnt[23]) {
		puts("是否拔北？");
		int x;
		cin>>x;
		if(x==0)break;
		cnt[23]--;
		cntbei[my]++;
		rep(i,0,len[my]+1)if(shoupai[my][i]==23) {
			swap(shoupai[my][i],shoupai[my][len[my]+1]);
			break;
		}
		sort(my);
		shoupai[my][len[my]+1]=pai[lingshang--];
		bottom--;
		cnt[shoupai[my][len[my]+1]]++;
		cout<<pl(my)<<"拔北"<<endl;
		printshoupai(1);
		if(ron()) {
			puts("是否自摸？");
			int x;
			cin>>x;
			if(x) {
				tsumo();
			}
		}
	}
	ll x=-1;
	while(x==-1) {
		puts("请问您切的牌是？");
		string s;
		cin>>s;
		ll num=tonum(s);
		rep(i,0,len[my]+1)if(shoupai[my][i]==num) {
			x=i;
			break;
		}
		if(x==-1)cout<<"此牌不合法或者不在您的手牌中，请重新输入！"<<endl;
	}
	ll qie=shoupai[my][x];
	cnt[qie]--;
	swap(shoupai[my][x],shoupai[my][len[my]+1]);
	sort(my);
	cout<<pl(my)<<"切出 "<<topai(qie)<<endl;
	paihe[my].push_back(qie);
}
void chk(ll qie) {
	string s=topai(qie);
	cout<<qie<<" "<<cnt[qie]<<endl;
	if(cnt[qie]>=2) {
		printshoupai();
		puts("是否碰？");
		ll x;
		cin>>x;
		if(x==1) {
			paihe[t].pop_back();
			ll qwq=len[my];
			rep(i,0,len[my]-2)if(shoupai[my][i]==qie) {
				swap(shoupai[my][i],shoupai[my][qwq--]);
				if(qwq==len[my]-2)break;
			}
			cnt[qie]-=2;
			len[my]-=3;
			fulu[my].push_back(s+s+s);
			sort(my,1);
			dapai(0);
			t=my;
			return;
		}
	}
	if(cnt[qie]>=3) {
		printshoupai();
		puts("是否杠？");
		ll x;
		cin>>x;
		if(x==1) {
			paihe[t].pop_back();
			ll qwq=len[my];
			rep(i,0,len[my]-3)if(shoupai[my][i]==qie) {
				swap(shoupai[my][i],shoupai[my][qwq--]);
				if(qwq==len[my]-3)break;
			}
			cnt[qie]-=3;
			len[my]-=3;
			shoupai[my][len[my]+1]=pai[lingshang--];
			cnt[shoupai[my][len[my]+1]]++;
			fulu[my].push_back(s+s+s+s);
			sort(my);
			dapai(0);
			t=my;
			return;
		}
	}
}
void aidapai() {
	ll qie=shoupai[t][len[t]+1];
	cout<<pl(t)<<"切出 "<<topai(qie)<<endl;
	fout<<pl(t)<<"切出 "<<topai(qie)<<endl;
	paihe[t].push_back(qie);
	cnt[qie]++;
	if(ron()) {
		printshoupai();
		puts("是否和牌？");
		int x;
		cin>>x;
		if(x) {
			cout<<pl(my)<<"荣和"<<pl(t)<<endl;
			fout<<pl(my)<<"荣和"<<pl(t)<<endl;
			shoupai[my][len[my]+1]=qie;
			rep(i,0,len[my]+1)cout<<topai(shoupai[my][i])<<" ";
			cout<<"\t";
			for(string x:fulu[my])cout<<x<<" ";
			cout<<endl;
			rep(i,0,len[my]+1)fout<<topai(shoupai[my][i])<<" ";
			fout<<"\t";
			for(string x:fulu[my])fout<<x<<" ";
			fout<<endl;
			exit(0);
		}
	}
	cnt[qie]--;
	chk(qie);
}
void print(ll t) {
	rep(i,0,len[t])cout<<topai(shoupai[t][i])<<" ";
	cout<<"\t";
	rep(i,1,cntbei[t])cout<<"4z";
	cout<<"\t";
	for(string x:fulu[t])cout<<x<<" ";
	cout<<endl;
	rep(i,0,len[t])fout<<topai(shoupai[t][i])<<" ";
	fout<<"\t";
	rep(i,1,cntbei[t])fout<<"4z";
	fout<<"\t";
	for(string x:fulu[t])fout<<x<<" ";
	fout<<endl;
}
void printpaihe() {
	rep(i,0,2) {
		cout<<pl(i)<<"：";
		for(ll x:paihe[i])cout<<topai(x)<<" ";
		cout<<"\t";
		rep(j,1,cntbei[i])cout<<"4z";
		cout<<"\t";
		for(string s:fulu[i])cout<<s<<" ";
		cout<<endl;
	}
}
void clear() {
	if(win==1)system("cls");
	else system("clear");
}
void pprint() {
	rep(i,0,2) {
		fout<<pl(i)<<"手牌：";
		rep(j,0,len[i])fout<<topai(shoupai[i][j])<<" ";
		fout<<"\t";
		for(string s:fulu[i])fout<<s<<" ";
		fout<<endl;
		fout<<pl(i)<<"牌河：";
		for(ll x:paihe[i])fout<<topai(x)<<" ";
		fout<<"\t";
		rep(j,1,cntbei[i])fout<<"4z";
		fout<<"\t\n";
	}
	fout<<"\n\n\n";
}
int main() {
	puts("请输入您的操作系统：1.Windows 2.Linux");
	cin>>win;
	clear();
	puts("牌堆生成中");
	rep(i,0,26)pai[i]=pai[i+27]=pai[i+54]=pai[i+81]=i;
	srand(time(0));
	random_shuffle(pai,pai+108);
	puts("发牌阶段");
	rep(i,0,2)len[i]=12;
	rep(i,0,2)rep(j,0,12)shoupai[i][j]=pai[i*13+j];
	top=52;
	bottom=108-14;
	lingshang=107;
	rep(i,0,2)sort(i);
	my=rand()%3;
	cout<<"您是："<<pl(my)<<endl;
	printshoupai();
	rep(i,0,12)cnt[shoupai[my][i]]++;
	getchar();
	getchar();
	puts("请输入牌谱保存位置：");
	string x;
	cin>>x;
	fout.open(x.c_str());
	clear();
	fout<<"牌山："<<endl;
	rep(i,top,107)fout<<pai[i]<<" ";
	fout<<endl;
	rep(i,0,2) {
		fout<<pl(i)<<"手牌："<<endl;
		rep(j,0,len[i])fout<<shoupai[i][j]<<" ";
		fout<<endl;
	}
	while(top<bottom) {
		shoupai[t][len[t]+1]=pai[top++];
		cout<<"剩余张数："<<bottom-top<<endl;
		fout<<"剩余张数："<<bottom-top<<endl;
		if(t==my)dapai();
		else aidapai();
		t=(t+1)%3;
		puts("牌河");
		printpaihe();
		printshoupai();
		pprint();
		getchar();
		getchar();
		clear();
	}
	puts("荒牌流局");
	fout<<"荒牌流局"<<endl;
	rep(i,0,2)print(i);
	return 0;
}//clang++-7 -pthread -std=c++17 -o main 三人麻将.cpp
//cd "d:\自编\"
//g++ 三人麻将.cpp -o 三人麻将.exe -std=c++14
//./三人麻将.exe